package org.song.aspectJ;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.song.model.entity.OperateLogEntity;
import org.song.model.threadlocal.WebContextUtil;
import org.song.util.FunctionUtil;
import org.song.util.JacksonUtil;
import org.song.mapper.OperateLogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 自定义注解日志横切记录
 */
@Aspect
@Component
@Slf4j
public class LogRecordAspect {

    // 使用@PointCut注解定义横切关注点，一般适用于横切到指定注解上和注解配合使用！！！！
    @Pointcut(value = "@annotation(org.song.annotation.LogRecord)")
    public void logRecordPointCut() {

    }

    @Autowired( required = true )
    @Qualifier( value = "operateLogMapper")
    private OperateLogMapper operateLogMapper;

    /**
     * 日志切面
     * @param joinPoint
     */
    @Before(value = "logRecordPointCut()")
    public void logRecordAspect(JoinPoint joinPoint) throws Throwable {
        // 当前用户

        try {
            // 请求参数
            final Object[] args = joinPoint.getArgs();
            // 请求实例Request
            final HttpServletRequest request = WebContextUtil.getCurrentRequest();
            if (Objects.isNull( request )) {
                log.error( "注解横切ThreadLocal容器获取Request实例为空: " + JacksonUtil.getJsonString( joinPoint ));
                return;
            }
            // 请求URL
            final String requestUri = request.getRequestURI();
            // 请求地址
            final String remoteAddr = FunctionUtil.getIpAddress(request);
            final OperateLogEntity operateLogEntity = OperateLogEntity.builder().id(operateLogMapper.makeLongKey())
                    .ip(remoteAddr)
                    .param(JacksonUtil.getJsonString(args))
                    .url(requestUri).build();
            // 操作日志落库
            operateLogMapper.insertSelective( operateLogEntity );
        } catch ( Exception e ) {
            log.error( "logRecordAspect AOP横切日志异常" + JacksonUtil.getJsonString( e.getMessage() ) );
        } finally {
            // ThreadLocal资源释放
    /*        WebContextUtil.removeCurrentRequest();
            WebContextUtil.removeCurrentResponse();*/
        }

    }

}
